package com.example.demo.component.k8s;

import com.example.demo.component.k8s.bean.configMap;
import com.example.demo.component.k8s.bean.deploy;
import com.example.demo.component.k8s.bean.pod;
import com.example.demo.component.k8s.bean.service;
import io.kubernetes.client.openapi.models.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName k8s_client_util
 * @Description
 * @date 2022/11/9 13:53
 * @Author yanceysong
 * @Version 1.0
 */
public class k8s_client_util {
    private static volatile long now;

    /**
     * inputStream 流转String
     *
     * @param is 流
     * @return String
     */
    protected static String stream2String(InputStream is) {
        BufferedReader bReader = new BufferedReader(new InputStreamReader(is));
        StringBuilder buffer = new StringBuilder();
        String line;
        try {
            now = System.currentTimeMillis();
            //因为传来的流没有结束，只能再开启一个线程模拟实现超时读取的过程
            new Thread(() -> {
                while (true) {
                    try {
                        if (System.currentTimeMillis() - now > 300) {
                            is.close();
                            break;
                        }
                        TimeUnit.MILLISECONDS.sleep(20);
                    } catch (InterruptedException | IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            while (true) {
                now = System.currentTimeMillis();
                line = bReader.readLine();
                if (line == null) break;
                buffer.append(line).append("\n");
            }
        } catch (IOException e) {
            return buffer.toString();
        } finally {
            try {
                bReader.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return buffer.toString();
    }
    private static final Integer RETRY_TIMES = 15;

    /**
     * 判断某个deploy当前的状态是否符合预期
     *
     * @param client    k8s的客户端
     * @param deploy    部署deploy
      * @return 结果
     */
    public static boolean check_deploy_status(k8s_client client, deploy deploy) throws InterruptedException {
        int now = 0;
        while (now++ < RETRY_TIMES) {
            List<deploy> deployList = client.get_deploy();
            for (deploy d : deployList) {
                if (d.getName().equalsIgnoreCase(deploy.getName())) {
                    if (Objects.requireNonNull(d.getV1Deployment().getStatus()).getUnavailableReplicas() == null)
                        return true;
                }
            }
            //睡
            TimeUnit.SECONDS.sleep(1);
        }
        throw new RuntimeException("检查服务部署结果出错!该服务可能没有部署成功，请ssh登录该服务器查看具体结果");
    }
    /**
     * k8s官方pod转内部实现pod
     *
     * @param v1Pod 官方pod
     * @return 内部实现pod
     */
    protected static pod V1Pod2pod(V1Pod v1Pod) {
        pod pod = new pod();
        pod.setV1Pod(v1Pod);
//        docker://12c6577988da2b0618d2b66cfaa68f8fb99a2db191447b113038ce033af6b8f2
        pod.setName(Objects.requireNonNull(v1Pod.getMetadata()).getName());
        pod.setPod_ip(Objects.requireNonNull(v1Pod.getStatus()).getPodIP());
        pod.setHost_ip(v1Pod.getStatus().getHostIP());
        pod.setContainer_name(Objects.requireNonNull(v1Pod.getStatus().getContainerStatuses()).get(0).getName());
        pod.setContainer_id(Objects.requireNonNull(v1Pod.getStatus().getContainerStatuses().get(0).getContainerID()).split(":")[1].substring(2));
        pod.setPhase(v1Pod.getStatus().getPhase());
        pod.setEvents(v1Pod.getStatus().getConditions());
        pod.setNamespace(Objects.requireNonNull(v1Pod.getMetadata()).getNamespace());
        pod.setRestart_count(v1Pod.getStatus().getContainerStatuses().get(0).getRestartCount());
        pod.setNode(Objects.requireNonNull(v1Pod.getSpec()).getNodeName());
        pod.setImage_name(v1Pod.getStatus().getContainerStatuses().get(0).getImage().split(":")[0]);
        pod.setImage_version(v1Pod.getStatus().getContainerStatuses().get(0).getImage().split(":")[1]);
        return pod;
    }

    /**
     * 对封装的pod内部改变版本号
     *
     * @param pod     内部pod
     * @param version 新的版本号
     * @return k8s的pod
     */
    public static V1Pod get_new_v1Pod(pod pod, String version) {
        Objects.requireNonNull(Objects.requireNonNull(pod.getV1Pod().getStatus()).getContainerStatuses()).get(0).setImage(pod.getImage_name() + ":" + version);
        return pod.getV1Pod();
    }

    /**
     * V1Service 转service
     *
     * @param v1Service k8s官方service
     * @return 内部实现service
     */
    protected static service V1Service2service(V1Service v1Service) {
        service service = new service();
        return service;
    }

    /**
     * k8s的deploy转内部的
     *
     * @param v1Deployment k8s的
     * @return 内部的
     */
    public static deploy V1Deploy2deploy(V1Deployment v1Deployment) {
        deploy deploy = new deploy();
        deploy.setName(v1Deployment.getMetadata().getName());
        deploy.setV1Deployment(v1Deployment);
        V1Container v1Container = Objects.requireNonNull(v1Deployment.getSpec()).getTemplate().getSpec().getContainers().get(0);
        deploy.setContainer_name(Objects.requireNonNull(v1Container.getName()));
        deploy.setImage_name(Objects.requireNonNull(v1Container.getImage()).split(":")[0]);
        deploy.setImage_version(v1Container.getImage().split(":")[1]);
        return deploy;
    }

    /**
     * 获取新的版本号的deploy
     *
     * @param deploy  内部的deploy
     * @param version 新的版本号
     * @return k8s的deploy
     */
    public static V1Deployment get_new_deploy(deploy deploy, String version) {
        V1Deployment v1Deployment = deploy.getV1Deployment();
        V1Container v1Container = Objects.requireNonNull(v1Deployment.getSpec()).getTemplate().getSpec().getContainers().get(0);
        v1Container.setImage(deploy.getImage_name() + ":" + version);
        return v1Deployment;
    }

    protected static configMap V1ConfigMap2configMap(V1ConfigMap v1ConfigMap) {
        configMap configMap = new configMap();
        return configMap;
    }
}
